__author__ = 'zhiweifan'
# 写平方和立方表
# str.rjust() 方法的演示，它把字符串输出到一列，并通过向左侧填充空格来使其右对齐。类似的方法还有 str.ljust() 和 str.center()
for x in range(1, 11):
    print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
    # Note use of 'end' on previous line
    print(repr(x*x*x).rjust(4))

for x in range(1, 11):
    print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
# str.zfill() 它用于向数值的字符串表达左侧填充 0。该函数可以正确理解正负号

# str.format() 调用时使用关键字参数，可以通过参数名来引用值
print('This {food} is {adjective}.'.format(food='spam', adjective='absolutely horrible'))

# '!a' (应用 ascii()), '!s' （应用 str() ） 和 '!r' （应用 repr() ） 可以在格式化之前转换值
import math
print('The value of PI is approximately {!r}.'.format(math.pi))

# 字段名后允许可选的 ':' 和格式指令。这允许对值的格式化加以更深入的控制
import math
print('The value of PI is approximately {0:.3f}.'.format(math.pi))

# 在字段后的 ':' 后面加一个整数会限定该字段的最小宽度
print('{0:10} ==> {1:10d}'.format("abc", 123))

# 如果你有个实在是很长的格式化字符串，不想分割它。如果你可以用命名来引用被格式化的变量而不是位置就好了。有个简单的方法，可以传入一个字典，用中括号访问它的键
table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; ' 'Dcab: {0[Dcab]:d}'.format(table))
# 也可以用 ‘**’ 标志将这个字典以关键字参数的方式传入
print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))
# 旧式的字符串格式化, 操作符 % 也可以用于字符串格式化
print('The value of PI is approximately %5.3f.' % math.pi)

#########################
# 文件读写
f = open('./../../../../test.txt', 'r')
# 第一个参数是一个标识文件名的字符串。第二个参数是由有限的字母组成的字符串，描述了文件将会被如何使用。
# 可选的 模式 有： 'r' ，此选项使文件只读； 'w' ，此选项使文件只写（对于同名文件，该操作使原有文件被覆盖）； 'a' ，此选项以追加方式打开文件； 'r+' ，此选项以读写方式打开文件；
#  模式 参数是可选的。如果没有指定，默认为 'r' 模式。
# 在 Windows 平台上， 'b' 模式以二进制方式打开文件，所以可能会有类似于 'rb' ， 'wb' ， 'r+b' 等等模式组合。
# Windows 平台上文本文件与二进制文件是有区别的，读写文本文件时，行尾会自动添加行结束符。
# 这种后台操作方式对 ASCII 文本文件没有什么问题，但是操作 JPEG 或 EXE 这样的二进制文件时就会产生破坏。
# 在操作这些文件时一定要记得以二进制模式打开。在 Unix 上，加一个 'b' 模式也一样是无害的，所以你可以一切二进制文件处理中平台无关的使用它。
# print(f.read)
# f.readline() 从文件中读取单独一行，字符串结尾会自动加上一个换行符（ \n ），只有当文件最后一行没有以换行符结尾时，这一操作才会被忽略
# print(f.readline())
# f.readlines() 返回一个列表，其中包含了文件中所有的数据行。如果给定了 sizehint 参数，就会读入多于一行的比特数，从中返回多行文本。
# print(f.readlines())

# 一种替代的方法是通过遍历文件对象来读取文件行
for line in f:
    print(line, end='')

# f.write(string) 方法将 string 的内容写入文件，并返回写入字符的长度

# f.tell() 返回一个整数，代表文件对象在文件中的指针位置，该数值计量了自文件开头到指针处的比特数。需要改变文件对象指针话话，使用 f.seek(offset,from_what) 。
# 指针在该操作中从指定的引用位置移动 offset 比特，引用位置由 from_what 参数指定。 from_what 值为 0 表示自文件起始处开始，
# 1 表示自当前文件指针位置开始，2 表示自文件末尾开始。 from_what 可以忽略，其默认值为零，此时从文件头开始。
# 当你使用完一个文件时，调用 f.close() 方法就可以关闭它并释放其占用的所有系统资源。 在调用 f.close() 方法后，试图再次使用文件对象将会自动失败
# 用关键字 with 处理文件对象是个好习惯。它的先进之处在于文件用完后会自动关闭，就算发生异常也没关系。它是 try-finally 块的简写
with open('/tmp/workfile', 'r') as f:
    read_data = f.read()
print(f.closed) # True

# 7.2.2. pickle 模块
# 我们可以很容易的读写文件中的字符串。数值就要多费点儿周折，因为 read() 方法只会返回字符串，应该将其传入 int() 这样的方法中，
# 就可以将 '123' 这样的字符转为对应的数值 123。不过，当你需要保存更为复杂的数据类型，例如列表、字典，类的实例，事情就会变得更复杂了。
# 好在用户不必要非得自己编写和调试保存复杂数据类型的代码。 Python 提供了一个名为 pickle 的标准模块。
# 这是一个令人赞叹的模块，几乎可以把任何 Python 对象 （甚至是一些 Python 代码段！）表达为为字符串，这一过程称之为封装 （ pickling ）。
# 从字符串表达出重新构造对象称之为拆封（ unpickling ）。封装状态中的对象可以存储在文件或对象中，也可以通过网络在远程的机器之间传输。
# 如果你有一个对象 x ，一个以写模式打开的文件对象 f ，封装对象的最简单的方法只需要一行代码:
# pickle.dump(x, f)
# 如果 f 是一个以读模式打开的文件对象，就可以重装拆封这个对象:
# x = pickle.load(f)
# （如果不想把封装的数据写入文件，这里还有一些其它的变化可用。完整的 pickle 文档请见Python 库参考手册）。
# pickle 是存储 Python 对象以供其它程序或其本身以后调用的标准方法。提供这一组技术的是一个 持久化 对象（ persistent object ）。
# 因为 pickle 的用途很广泛，很多 Python 扩展的作者都非常注意类似矩阵这样的新数据类型是否适合封装和拆封。
import pickle
# f = open('./test.txt', 'wb')
# a = {1,2,3,"中文"}
# pickle.dump(str(a), f)
# f.close()
f2 = open('./test.txt', 'rb')
b = pickle.load(f2)
f2.close()
print(b)